/*
 * Copyright (c) 2017 深圳市高德威技术有限公司  All rights reserved.
 *
 * package_buffer.c
 *
 *  Created on: 2017年3月27日
 *      Author: chenshisheng
 */


#include "package_buffer.h"

/**
 *
 * @param pb
 * @param buf
 * @param size
 * @param elemMaxSize
 * @note size 值必须为2的n次方
 */
void PackageBuffer_Init(pbuf_t *pb, void *buf, unsigned int size, unsigned int elemMaxSize)
{
    pb->start = 0;
    pb->end = 0;
    pb->size = size;
    pb->elemMaxSize = elemMaxSize;
    pb->buf = buf;
}

#define _IS_FULL(pb, end) (end == (pb->start ^ pb->size))
#define _IS_EMPTY(pb) (pb->end == pb->start)
#define _INCR(pb, p) ((p + 1) & (2 * pb->size - 1))

int PackageBuffer_Write(pbuf_t *pb, const void *dataIn, unsigned int pkgSize)
{
    int ret;
    const uint8_t *vdata;
    unsigned int end, i;

    vdata = dataIn;
    end = pb->end;
    ret = 0;

    if(pkgSize > pb->elemMaxSize)
    {
        debug("PBuf Error: data too large!\n");
        return -1;
    }

    if(_IS_FULL(pb, pb->end))
    {
        return -1;
    }

    pb->buf[end & (pb->size - 1)] = (uint8_t) pkgSize;
    end = _INCR(pb, end);

    for(i = 0; i < pkgSize; i++)
    {
        if(_IS_FULL(pb, end))
        {
            ret = -1;
            break;
        }

        pb->buf[end & (pb->size - 1)] = vdata[i];
        end = _INCR(pb, end);
    }

    if(ret == 0)
    {
        pb->end = end;
    }

    return ret;
}

int PackageBuffer_Read(pbuf_t *pb, void *dataOut, unsigned int *pkgSize)
{
    int8_t ret;
    uint8_t *vdata;
    unsigned int size, i;

    if(_IS_EMPTY(pb))
    {
        return -1;
    }

    ret = 0;
    vdata = dataOut;

    size = pb->buf[pb->start & (pb->size - 1)];
    *pkgSize = size;
    pb->start = _INCR(pb, pb->start);
    if(size > pb->elemMaxSize)
    {
        return -1;
    }

    for(i = 0; i < size; i ++)
    {
        if(_IS_EMPTY(pb))
        {
            ret = -1;
            break;
        }

        vdata[i] = pb->buf[pb->start & (pb->size - 1)];
        pb->start = _INCR(pb, pb->start);
    }

    return ret;
}

